/**
 * WebSock api
 */

function WebSock(host, port, clientId, user, password, dest) {
	//定义变量
	const attrData = "rtdata"; //标识符
	var isPolling = false; //是否定时调用
	var registerMap = new Map(); //保存注册的函数 key为tag，value为函数
	var dataMap = new Map(); //保存后台数据
	var interval = null; //定时器
	var currentPeriod = 0; //当前定时器周期，为0定时器关闭
	var auto = false; //是否自动更新标签
	var domsSet = new Set(); //保存页面所有dom节点
	var newPushTags = new Set(); //新进入的标签
	var getAllTag = function() {
			if(auto == false || domsSet.size == 0) {
				searchAllDom();
			}
			var result = [];
			domsSet.forEach(function(element, sameElement, set) {
				result.push(element);
			});
			return result;
		},
		upDataDoms = function() {
			domsSet.clear();
			searchAllDom();
		},
		searchAllDom = function() { //搜索所有dom节点
			$("body *:not('.content')").each(function(i, obj) {
				var objId = $(obj).attr(attrData);
				if(objId) {
					domsSet.add(objId);
				}
			});
		},
		setAuto = function(flag) { //设置自动更新dom值
			if(!flag) {
				return;
			}
			if(flag == false) {
				auto = false;
				upDataDoms();
			} else {
				auto = true;
				searchAllDom();
			}
		},
		setDomValue = function(key) { //设置dom值
			var v = getValue(key);
			var dmos = $("*[" + attrData + "='" + key + "'");
			//查找对应的dom元素更新值
			for(var i = 0; i < dmos.length; i++) {
				$(dmos[i]).html(v);
			}
		},
		doUpDataDomValue = function(key) {
			//如果注册了函数调用函数
			if(domsSet.has(key)) {
				setDomValue(key);
			}
			var funs = registerMap.get(key);
			if(funs) {
				funs.forEach(function(index, fun, set) {
					fun(key);
				});
			}
		},
		doInterval = function() { //执行定时任务
			if(newPushTags.size == 0) {
				return;
			}
			newPushTags.forEach(function(index, key, set) {
				doUpDataDomValue(key);
			});
			//清空本次已经更新的值
			newPushTags.clear();
		},
		setPolling = function(period) { //设置定时周期
			if(!period || currentPeriod == period) {
				return;
			}
			if(interval) {
				//清理之前的周期函数
				clearInterval(interval);
			}
			if(period == 0) {
				//设置周期为0清理周期函数
				isPolling = false;
			} else {
				//设置周期
				isPolling = true;
				interval = setInterval(doInterval, period);
			}
			currentPeriod = period;
		},
		bytArrayToDouble = function(payloadBytes) { //byte数组转化浮点数，小端存储
			return new DataView(payloadBytes.slice(0, 8).buffer).getFloat64(0, true);
		},
		getValue = function(tag) { //获取某个标签的值
			var msg = dataMap.get(tag);
			if(!msg) {
				//无数据返回null
				return null;
			}
			var payloadBytes = msg.payloadBytes;
			//判断为num或者str
			if(payloadBytes.byteLength == 8) {
				return bytArrayToDouble(payloadBytes);
			} else {
				return msg.payloadString;
			}
		},
		register = function(fun, tags) { //注册标签和函数
			if(!fun || !tags) {
				return;
			}
			//注册数组tags
			if(tags instanceof Array) {
				for(i in tags) {
					var tag = tags[i];
					var funs = registerMap.get(tag);
					if(!funs) {
						funs = new Set();
						registerMap.set(tag, funs);
					}
					funs.add(fun);
				}
			} else {
				var funs = registerMap.get(tags);
				if(!funs) {
					funs = new Set();
					registerMap.set(tags, funs);
				}
				funs.add(fun);
			}
		},
		onConnect = function(frame) { //mqtt连接成功回调
			client.subscribe(destination);
			console.log("mqtt connect to [%s] success", dest)
		},
		onConnectionLost = function() { //mqtt连接丢失回调
			console.log("mqtt [%s] disconnect", dest)
		},
		onFailure = function() { //mqtt连接失败回调
			console.log("mqtt connect to [%s] fail", dest)
		},
		callBack = function(msg) { //数据推送回调
			var tag = msg.destinationName;
			var funs = registerMap.get(tag);
			if(funs || domsSet.has(tag)) {
				dataMap.set(tag, msg)
				if(isPolling == false) {
					doUpDataDomValue(tag);
				} else {
					newPushTags.add(tag);
				}
			};
		};
	this.host = host; //主机ip或域名
	this.clientId = clientId; //自定义客户id
	this.user = user; //用户名
	this.password = password; //密码
	this.dest = dest; //订阅主题
	this.register = register; //对外提供的注册函数
	this.getValue = getValue; //对外提供的获取tag值函数
	this.auto = setAuto; //设置自动更新
	this.setPolling = setPolling; //设置定时时间
	this.getAllTag = getAllTag;
	this.upDataDoms = upDataDoms;
	var client = new Paho.MQTT.Client(host, Number(port), clientId); //初始化连接对象
	client.onConnect = onConnect; //设置设置连接成功回调
	client.onMessageArrived = callBack; //设置数据推送回调
	client.onConnectionLost = onConnectionLost; //设置连接丢失回调
	client.connect({ //开始连接
		userName: user,
		password: password,
		onSuccess: onConnect,
		onFailure: onFailure
	});
}